home *** CD-ROM | disk | FTP | other *** search
/ Visual Cafe 3 / Visual Cafe 3.ISO / Vcafe / Source.bin / SplitterPanel.java < prev    next >
Text File  |  1998-09-23  |  84KB  |  2,674 lines

  1. package symantec.itools.awt;
  2.  
  3. import java.awt.Panel;
  4. import java.awt.Component;
  5. import java.awt.Dimension;
  6. import java.awt.Point;
  7. import java.awt.Color;
  8. import java.awt.Rectangle;
  9. import java.awt.LayoutManager;
  10. import java.awt.Graphics;
  11. import java.awt.Container;
  12. import java.awt.Event;
  13. import java.awt.Cursor;
  14. import java.beans.PropertyVetoException;
  15. import java.beans.PropertyChangeEvent;
  16. import java.beans.VetoableChangeListener;
  17. import java.beans.PropertyChangeListener;
  18. import java.awt.event.MouseEvent;
  19. import java.awt.event.MouseListener;
  20. import java.util.ResourceBundle;
  21.  
  22. //  05/07/97    CAR Added implementation for getComponents() which is now called by AWT code.
  23. //  07/17/97    LAB Updated version to 1.1.  Updated event handling to JDK 1.1.  Bound and constrained
  24. //                    properties.  Added add/removeNotify for listener registration.  Changed references
  25. //                    to setCursor to use Component's setCursor rather than Frame's. Added MoveSplitCursor
  26. //                    property.  Added Use3DBorder property.  Added AllowDynamicMoving property.
  27. //  07/28/97    CAR marked fields transient as needed
  28. //                  inner classes implement java.io.Serializable
  29. //  08/29/97    CAR modified preferredSize
  30.  
  31. /**
  32.  * Use to create a container that can be divided into a number of subpanels which
  33.  * holds visual components and other panels, and specifically to:
  34.  * <UL>
  35.  * <DT>╖ Create a subcontainer that organizes container space within an Applet,
  36.  * Frame or Dialog container. This simplifies your component layout task.</DT>
  37.  * <DT>╖ Hold other specialized Panel containers.</DT>
  38.  * </UL>
  39.  * The SplitterPanel component is the parent Panel containing a set of
  40.  * subpanels. You must write code to divide the parent panel into subpanels.
  41.  * You must set panel defaults in your project source code.
  42.  * <p>
  43.  * The SplitterPanel automatically recognizes the mouseDragged as the command
  44.  * to resize the appropriate subpanel boundary.
  45.  * <p>
  46.  * Subpanels can be resized at runtime by dragging panel borders with the mouse.
  47.  * <p>
  48.  * This code example splits a SplitterPanel into four subpanels and adds a
  49.  * button to two of the subpanels.
  50.  * <UL><pre>
  51.  * splitterPanel1.split(splitterPanel1.SPLIT_HORIZONTAL);
  52.  * splitterPanel1.getTopPanel().split(splitterPanel1.SPLIT_VERTICAL);
  53.  * splitterPanel1.getBottomPanel().split(splitterPanel1.SPLIT_VERTICAL);
  54.  * // add a button to the top left panel
  55.  * splitterPanel1.getTopLeftPanel().add(new Button("Top Left"));
  56.  * // add a button to the lower right panel
  57.  * splitterPanel1.getBottomRightPanel().add(new Button("Bottom Right"));
  58.  * </pre></UL>
  59.  * Individual subpanels can be accessed in code using any of these methods:
  60.  * getBottomLeftPanel,
  61.  * getBottomPanel,
  62.  * getBottomRightPanel,
  63.  * getLeftPanel,
  64.  * getRightPanel,
  65.  * getSub2Panel,
  66.  * getSubPanel,
  67.  * getTopLeftPanel,
  68.  * getTopPanel,
  69.  * getTopRightPanel.
  70.  * <p>
  71.  *
  72.  * @version 1.1, July 15, 1997
  73.  * @author  Symantec
  74.  */
  75. public class SplitterPanel extends Panel
  76. {
  77.     /**
  78.      * Vertical panel split constant for the SplitterPanel constructor.
  79.      * This splits the panel into two vertical panels.
  80.      */
  81.      // @see symantec.itools.awt.SplitterPanel#SplitterPanel(int, int, int)
  82.     public static final int SPLIT_VERTICAL = 1;
  83.  
  84.     /**
  85.      * Horizontal panel split constant for the SplitterPanel constructor.
  86.      * This splits the panel into two horizontal panels.
  87.      */
  88.      // @see symantec.itools.awt.SplitterPanel#SplitterPanel(int, int, int)
  89.     public static final int SPLIT_HORIZONTAL = 2;
  90.  
  91.     /**
  92.      * Indicates a vertical panel split. The panel contains/will
  93.      * contain two subpanels, left and right.
  94.      * @see #split
  95.      */
  96.     public static final int SPLIT_VER = SPLIT_VERTICAL;
  97.  
  98.     /**
  99.      * Indicates a horizontal panel split. The panel contains/will
  100.      * contain two subpanels, top and bottom.
  101.      * @see #split
  102.      */
  103.     public static final int SPLIT_HOR = SPLIT_HORIZONTAL;
  104.  
  105.     /**
  106.      * Panel split constant for the SplitterPanel constructor.
  107.      * This splits the panel into four panels by first splitting horizontally then
  108.      * splitting vertically.
  109.      */
  110.      // @see symantec.itools.awt.SplitterPanel#SplitterPanel(int, int, int)
  111.     public static final int SPLIT_BOTH = 3;
  112.  
  113.     /**
  114.      * Panel split constant for the SplitterPanel constructor.
  115.      * This splits the panel into four panels by first splitting vertically then
  116.      * splitting horizontally.
  117.      */
  118.      // @see symantec.itools.awt.SplitterPanel#SplitterPanel(int, int, int)
  119.     public static final int SPLIT_BOTH_V = 4;
  120.  
  121.     /**
  122.      * Panel split constant for the SplitterPanel constructor.
  123.      * This splits the panel into three panels, with a single larger panel on the
  124.      * right.
  125.      */
  126.      // @see symantec.itools.awt.SplitterPanel#SplitterPanel(int, int, int)
  127.     public static final int SPLIT3_LEFT = 5;
  128.  
  129.     /**
  130.      * Panel split constant for the SplitterPanel constructor.
  131.      * This splits the panel into three panels, with a single larger panel on the
  132.      * left.
  133.      */
  134.      // @see symantec.itools.awt.SplitterPanel#SplitterPanel(int, int, int)
  135.     public static final int SPLIT3_RIGHT = 6;
  136.  
  137.     /**
  138.      * Panel split constant for the SplitterPanel constructor.
  139.      * This splits the panel into three panels, with a single larger panel on the
  140.      * bottom.
  141.      */
  142.      // @see symantec.itools.awt.SplitterPanel#SplitterPanel(int, int, int)
  143.     public static final int SPLIT3_TOP = 7;
  144.  
  145.     /**
  146.      * Panel split constant for the SplitterPanel constructor.
  147.      * This splits the panel into three panels, with a single larger panel on the
  148.      * top.
  149.      */
  150.      // @see symantec.itools.awt.SplitterPanel#SplitterPanel(int, int, int)
  151.     public static final int SPLIT3_BOTTOM = 8;
  152.  
  153.     /**
  154.      * Constructs a new default SplitterPanel.
  155.      * By default, all the gap sizes are 3 and all the border sizes 2.
  156.      * @see #setGapSizes(int, int, int, int)
  157.      * @see #setBdrSizes(int, int)
  158.      */
  159.     public SplitterPanel()
  160.     {
  161.         this(true);
  162.     }
  163.  
  164.     /**
  165.      * Constructs a new SplitterPanel of the specified size which
  166.      * is ready to be split into panels.
  167.      * By default, all the gap sizes are 3 and all the border sizes 2.
  168.      * @param spWidth the initial width of the SplitterPanel, in pixels
  169.      * @param spHeight the initial height of the SplitterPanel, in pixels
  170.      * @see #setGapSizes(int, int, int, int)
  171.      * @see #setBdrSizes(int, int)
  172.      */
  173.     public SplitterPanel(int spWidth, int spHeight)
  174.     {
  175.         this(true);
  176.  
  177.         if (this == null)
  178.             return;
  179.  
  180.         resize(spWidth, spHeight);
  181.     }
  182.  
  183.     /**
  184.      * Constructs a new SplitterPanel of specified size which is
  185.      * split into panels.
  186.      * By default, all the gap sizes are 3 and all the border sizes 2.
  187.      * @param spWidth the initial width of the SplitterPanel, in pixels
  188.      * @param spHeight the initial height of the SplitterPanel, in pixels
  189.      * @param splitSpec specifies how to split up the panel
  190.      * @see #SPLIT_VERTICAL
  191.      * @see #SPLIT_HORIZONTAL
  192.      * @see #SPLIT_BOTH
  193.      * @see #SPLIT_BOTH_V
  194.      * @see #SPLIT3_LEFT
  195.      * @see #SPLIT3_RIGHT
  196.      * @see #SPLIT3_TOP
  197.      * @see #SPLIT3_BOTTOM
  198.      * @see #setGapSizes(int, int, int, int)
  199.      * @see #setBdrSizes(int, int)
  200.      */
  201.     public SplitterPanel(int spWidth, int spHeight, int splitSpec)
  202.     {
  203.         this(splitSpec);
  204.  
  205.         if (this == null)
  206.             return;
  207.  
  208.         resize(spWidth, spHeight);
  209.     }
  210.  
  211.     /**
  212.      * Constructs a new SplitterPanel which is split into panels.
  213.      * By default, all the gap sizes are 3 and all the border sizes 2.
  214.      * @param splitSpec specifies how to split up the panel
  215.      * @see #SPLIT_VERTICAL
  216.      * @see #SPLIT_HORIZONTAL
  217.      * @see #SPLIT_BOTH
  218.      * @see #SPLIT_BOTH_V
  219.      * @see #SPLIT3_LEFT
  220.      * @see #SPLIT3_RIGHT
  221.      * @see #SPLIT3_TOP
  222.      * @see #SPLIT3_BOTTOM
  223.      * @see #setGapSizes(int, int, int, int)
  224.      * @see #setBdrSizes(int, int)
  225.      */
  226.     public SplitterPanel(int splitSpec)
  227.     {
  228.         this(splitSpec, null, null, null, null);
  229.     }
  230.  
  231.     /**
  232.      * Constructs a new SplitterPanel which is split into panels
  233.      * to which components are added.
  234.      * By default, all the gap sizes are 3 and all the border sizes 2.
  235.      * @param splitSpec specifies how to split up the panel
  236.      * @param compR1C1 specifies the component in row 1, column 1 (top, left)
  237.      * @param compR1C2 specifies the component in row 1, column 2 (top, right)
  238.      * @param compR2C1 specifies the component in row 2, column 1 (bottom, left)
  239.      * @param compR2C2 specifies the component in row 2, column 2 (bottom, right)
  240.      * @see #SPLIT_VERTICAL
  241.      * @see #SPLIT_HORIZONTAL
  242.      * @see #SPLIT_BOTH
  243.      * @see #SPLIT_BOTH_V
  244.      * @see #SPLIT3_LEFT
  245.      * @see #SPLIT3_RIGHT
  246.      * @see #SPLIT3_TOP
  247.      * @see #SPLIT3_BOTTOM
  248.      * @see #setGapSizes(int, int, int, int)
  249.      * @see #setBdrSizes(int, int)
  250.      */
  251.     public SplitterPanel(int splitSpec, Component compR1C1, Component compR1C2, Component compR2C1, Component compR2C2)
  252.     {
  253.         this(true);
  254.  
  255.         if (this == null)
  256.             return;
  257.  
  258.         switch (splitSpec)
  259.         {
  260.             case SPLIT_NONE:
  261.             {
  262.                 if (compR1C1 != null) this.add(compR1C1);
  263.                 break;
  264.             }
  265.             case SPLIT_VERTICAL:
  266.             {
  267.                 split(SPLIT_VER, compR1C1, compR1C2);
  268.                 break;
  269.             }
  270.             case SPLIT_HORIZONTAL:
  271.             {
  272.                 split(SPLIT_HOR, compR1C1, compR2C1);
  273.                 break;
  274.             }
  275.             case SPLIT_BOTH:
  276.             {
  277.                 split(SPLIT_HOR);
  278.                 getSubPanel(1).split(SPLIT_VER, compR1C1, compR1C2);
  279.                 getSubPanel(2).split(SPLIT_VER, compR2C1, compR2C2);
  280.                 break;
  281.             }
  282.             case SPLIT_BOTH_V:
  283.             {
  284.                 split(SPLIT_VER);
  285.                 getSubPanel(1).split(SPLIT_HOR, compR1C1, compR2C1);
  286.                 getSubPanel(2).split(SPLIT_HOR, compR1C2, compR2C2);
  287.                 break;
  288.             }
  289.             case SPLIT3_LEFT:
  290.             {
  291.                 split(SPLIT_VER, null, compR1C2);
  292.                 getSubPanel(1).split(SPLIT_HOR, compR1C1, compR2C1);
  293.                 break;
  294.             }
  295.             case SPLIT3_RIGHT:
  296.             {
  297.                 split(SPLIT_VER, compR1C1, null);
  298.                 getSubPanel(2).split(SPLIT_HOR, compR1C2, compR2C2);
  299.                 break;
  300.             }
  301.             case SPLIT3_TOP:
  302.             {
  303.                 split(SPLIT_HOR, null, compR2C1);
  304.                 getSubPanel(1).split(SPLIT_VER, compR1C1, compR1C2);
  305.                 break;
  306.             }
  307.             case SPLIT3_BOTTOM:
  308.             {
  309.                 split(SPLIT_HOR, compR1C1, null);
  310.                 getSubPanel(2).split(SPLIT_VER, compR2C1, compR2C2);
  311.                 break;
  312.             }
  313.  
  314.         }
  315.     }
  316.  
  317.     private SplitterPanel(boolean isOuter)
  318.     {
  319.         super();
  320.  
  321.         this.isOuter = isOuter;
  322.         heightOnly = false;
  323.         widthOnly  = false;
  324.         allowDynamicMoving = false;
  325.         splitType = SPLIT_NONE;
  326.  
  327.         // Set defaults
  328.         minDim  = new Dimension(0, 0);
  329.         curDim  = new Dimension(0, 0);
  330.         curLoc  = new Point(0, 0);
  331.         prefDim = new Dimension(0, 0);
  332.  
  333.         try
  334.         {
  335.             setGapColor(Color.lightGray);
  336.         }
  337.         catch (PropertyVetoException exc) {}
  338.  
  339.         iGapWidth  = 3;
  340.         iGapHeight = 3;
  341.         iBdrSize   = 2;
  342.         oGapWidth  = 3;
  343.         oGapHeight = 3;
  344.         oBdrSize   = 2;
  345.  
  346.         //If outer, then create the REQUIRED first inner Panel
  347.         if (isOuter)
  348.         {
  349.             innerSP = new SplitterPanel(false);
  350.             super.add(innerSP, -1);
  351.             outerSP = this;
  352.             innerSP.outerSP = this;
  353.  
  354.             layout();
  355.         }
  356.  
  357.     }
  358.  
  359.     //--------------------------------------------------
  360.     // accessor methods
  361.     //--------------------------------------------------
  362.  
  363.     /**
  364.      * This flag specifies how to draw the border around panels.
  365.      * @param flag if true, the border around the panel is drawn in a three dimensional way.
  366.      * @exception PropertyVetoException
  367.      * if the specified property value is unacceptable
  368.      * @see #isUse3DBorder
  369.      */
  370.     public void setUse3DBorder(boolean flag) throws PropertyVetoException
  371.     {
  372.         if(use3dBdr != flag)
  373.         {
  374.             Boolean oldValue = new Boolean(use3dBdr);
  375.             Boolean newValue = new Boolean(flag);
  376.  
  377.             vetos.fireVetoableChange("Use3DBorder", oldValue, newValue);
  378.  
  379.             use3dBdr = flag;
  380.  
  381.             changes.firePropertyChange("Use3DBorder", oldValue, newValue);
  382.         }
  383.     }
  384.  
  385.     /**
  386.      * This flag specifies how to draw the border around panels.
  387.      * @return flag if true, the border around the panel is drawn in a three dimensional way.
  388.      * @see #setUse3DBorder
  389.      */
  390.     public boolean isUse3DBorder()
  391.     {
  392.         return use3dBdr;
  393.     }
  394.  
  395.     /**
  396.      * This flag specifies if moving of a split in a splitter panel will be real time, or delayed until mouse released.
  397.      * @param flag if true, when a split is moved, it will dynamically resize the panels the split affects. If false,
  398.      * the resizing will happen when the mouse is released.
  399.      * @exception PropertyVetoException
  400.      * if the specified property value is unacceptable
  401.      * @see #isAllowDynamicMoving
  402.      */
  403.     public void setAllowDynamicMoving(boolean flag) throws PropertyVetoException
  404.     {
  405.         if(allowDynamicMoving != flag)
  406.         {
  407.             Boolean oldValue = new Boolean(allowDynamicMoving);
  408.             Boolean newValue = new Boolean(flag);
  409.  
  410.             vetos.fireVetoableChange("AllowDynamicMoving", oldValue, newValue);
  411.  
  412.             allowDynamicMoving = flag;
  413.             propagateChanges();
  414.  
  415.             changes.firePropertyChange("AllowDynamicMoving", oldValue, newValue);
  416.         }
  417.     }
  418.  
  419.     /**
  420.      * This flag specifies if moving of a split in a splitter panel will be real time, or delayed until mouse released.
  421.      * @return true if when a split is moved, it will dynamically resize the panels the split affects. If false,
  422.      * the resizing will happen when the mouse is released.
  423.      * @see #setAllowDynamicMoving
  424.      */
  425.     public boolean isAllowDynamicMoving()
  426.     {
  427.         return allowDynamicMoving;
  428.     }
  429.  
  430.     /**
  431.      * Gets the type of split for this SplitterPanel.
  432.      * @return the splitType: SPLIT_VERTICAL or SPLIT_HORIZONTAL
  433.      * @see #SPLIT_VERTICAL
  434.      * @see #SPLIT_HORIZONTAL
  435.      */
  436.     public int getSplitType()
  437.     {
  438.         SplitterPanel targetSP = this;
  439.         if (isOuter) targetSP = this.innerSP;
  440.         return targetSP.splitType;
  441.     }
  442.  
  443.     /**
  444.      * Determines the cursor to use when dragging the split between panels.
  445.      * Use Cursor.HAND_CURSOR, etc to choose a cursor
  446.      * @param newCursor the new Cursor to use.
  447.      * @exception PropertyVetoException
  448.      * if the specified property value is unacceptable
  449.      * @see #getMoveSplitCursor
  450.      * @see #setMoveSplitCursor(int)
  451.      */
  452.     public void setMoveSplitCursor(Cursor newCursor) throws PropertyVetoException
  453.     {
  454.         if(!symantec.itools.util.GeneralUtils.objectsEqual(moveSplitCursor, newCursor))
  455.         {
  456.             Cursor oldValue = moveSplitCursor;
  457.  
  458.             vetos.fireVetoableChange("MoveSplitCursor", oldValue, newCursor);
  459.  
  460.             moveSplitCursor = newCursor;
  461.  
  462.             changes.firePropertyChange("MoveSplitCursor", oldValue, newCursor);
  463.         }
  464.     }
  465.  
  466.     /**
  467.      * Determines the cursor to use when dragging the split between panels.
  468.      * Use Cursor.HAND_CURSOR, etc to choose a cursor
  469.      * @param newCursor the integer value of a Cursor to use.
  470.      * @exception PropertyVetoException
  471.      * if the specified property value is unacceptable
  472.      * @see #getMoveSplitCursor
  473.      * @see #setMoveSplitCursor(java.awt.Cursor)
  474.      * @see java.awt.Cursor#DEFAULT_CURSOR
  475.      * @see java.awt.Cursor#CROSSHAIR_CURSOR
  476.      * @see java.awt.Cursor#TEXT_CURSOR
  477.      * @see java.awt.Cursor#WAIT_CURSOR
  478.      * @see java.awt.Cursor#SW_RESIZE_CURSOR
  479.      * @see java.awt.Cursor#SE_RESIZE_CURSOR
  480.      * @see java.awt.Cursor#NW_RESIZE_CURSOR
  481.      * @see java.awt.Cursor#NE_RESIZE_CURSOR
  482.      * @see java.awt.Cursor#N_RESIZE_CURSOR
  483.      * @see java.awt.Cursor#S_RESIZE_CURSOR
  484.      * @see java.awt.Cursor#W_RESIZE_CURSOR
  485.      * @see java.awt.Cursor#E_RESIZE_CURSOR
  486.      * @see java.awt.Cursor#HAND_CURSOR
  487.      * @see java.awt.Cursor#MOVE_CURSOR
  488.      */
  489.     public void setMoveSplitCursor(int newCursor) throws PropertyVetoException, IllegalArgumentException
  490.     {
  491.         setMoveSplitCursor(new Cursor(newCursor));
  492.     }
  493.  
  494.     /**
  495.      * The cursor to use when dragging the split between panels.
  496.      * @return the Cursor to be used when dragginf the split between panels.
  497.      * @see #setMoveSplitCursor(java.awt.Cursor)
  498.      * @see #setMoveSplitCursor(int)
  499.      */
  500.     public Cursor getMoveSplitCursor()
  501.     {
  502.         return moveSplitCursor;
  503.     }
  504.  
  505.     /**
  506.      * Sets the color of the gap between panels and around the outside
  507.      * border.
  508.      * @param c the color to use
  509.      * @exception PropertyVetoException
  510.      * if the specified property value is unacceptable
  511.      * @see #getGapColor
  512.      */
  513.     public void setGapColor(Color c) throws PropertyVetoException
  514.     {
  515.         if(!symantec.itools.util.GeneralUtils.objectsEqual(gapColor, c))
  516.         {
  517.             Color oldValue = this.gapColor;
  518.  
  519.             vetos.fireVetoableChange("GapColor", oldValue, c);
  520.  
  521.             this.gapColor = new Color(c.getRed(), c.getGreen(), c.getBlue());
  522.             propagateChanges();
  523.  
  524.             changes.firePropertyChange("GapColor", oldValue, c);
  525.         }
  526.     }
  527.  
  528.     /**
  529.      * Gets the color of the gap between panels and around the outside border.
  530.      * @return the current gap color
  531.      * @see #setGapColor
  532.      */
  533.     public Color getGapColor()
  534.     {
  535.         return this.gapColor;
  536.     }
  537.  
  538.     /**
  539.      * @deprecated
  540.      * @see getGapColor
  541.      */
  542.     public Color gapColor()
  543.     {
  544.         return getGapColor();
  545.     }
  546.  
  547.     /**
  548.      * Sets the "enforce minimum dimension" mode.
  549.      * This mode prevents the dragging of a split between panels
  550.      * from making a panel smaller than the minimum size of its component.
  551.      * @param theFlag if true enforces minimum panel dimensions
  552.      * @exception PropertyVetoException
  553.      * if the specified property value is unacceptable
  554.      * @see #isEnforceMinDim
  555.      */
  556.     public void setEnforceMinDim(boolean theFlag) throws PropertyVetoException
  557.     {
  558.         if(enforceMinDim != theFlag)
  559.         {
  560.             Boolean oldValue = new Boolean(enforceMinDim);
  561.             Boolean newValue = new Boolean(theFlag);
  562.  
  563.             vetos.fireVetoableChange("EnforceMinDim", oldValue, newValue);
  564.  
  565.             enforceMinDim = theFlag;
  566.             propagateChanges();
  567.  
  568.             changes.firePropertyChange("EnforceMinDim", oldValue, newValue);
  569.         }
  570.     }
  571.  
  572.     /**
  573.      * Gets the current "enforce minimum dimension" mode.
  574.      * This mode prevents the dragging of a split between panels
  575.      * from making a panel smaller than the minimum size of its component.
  576.      * @return true if minimum panel dimensions are enforced
  577.      * @see #setEnforceMinDim
  578.      */
  579.     public boolean isEnforceMinDim()
  580.     {
  581.         return enforceMinDim;
  582.     }
  583.  
  584.     /**
  585.      * @deprecated
  586.      * @see #isEnforceMinDim
  587.      */
  588.     public boolean getEnforceMinDim()
  589.     {
  590.         return isEnforceMinDim();
  591.     }
  592.  
  593.     /**
  594.      * Sets the "resize propagation" mode.
  595.      * Set this to false to prevent the automatic resizing of SplitterPanel
  596.      * panels from also calling resize() for the component that you add.
  597.      * The default behavior propagates the resizing effect of dragging the
  598.      * split between panes by calling move and resize for the panels that have
  599.      * been added to those panes.  Clearing this introduces a clipping effect,
  600.      * rather than a scaling effect.
  601.      * @param theFlag if true, resize propagation is enabled; if false,
  602.      * resize propagation is disabled
  603.      * @exception PropertyVetoException
  604.      * if the specified property value is unacceptable
  605.      * @see #isPropResize
  606.      */
  607.     public void setPropResize(boolean theFlag) throws PropertyVetoException
  608.     {
  609.         if(propResize != theFlag)
  610.         {
  611.             Boolean oldValue = new Boolean(propResize);
  612.             Boolean newValue = new Boolean(theFlag);
  613.  
  614.             vetos.fireVetoableChange("PropResize", oldValue, newValue);
  615.  
  616.             //Controls whether reshapes are propagated into added components
  617.             propResize = theFlag;
  618.             propagateChanges();
  619.  
  620.             changes.firePropertyChange("PropResize", oldValue, newValue);
  621.         }
  622.     }
  623.  
  624.     /**
  625.      * Gets the current "resize propagation" mode.
  626.      * When this mode is enabled, the resizing effect of dragging the split
  627.      * between panes is propagated by reshaping the panels that have been
  628.      * added to those panes. This results in a scaling effect.
  629.      * When this mode is disabled this doesn't happen, resulting in a
  630.      * clipping effect.
  631.      * This mode is enabled by default.
  632.      * @return the current "resize propagation" mode
  633.      * @see #setPropResize
  634.      */
  635.     public boolean isPropResize()
  636.     {
  637.         return propResize;
  638.     }
  639.  
  640.     /**
  641.      * @deprecated
  642.      * @see #isPropResize
  643.      */
  644.     public boolean getPropResize()
  645.     {
  646.         return isPropResize();
  647.     }
  648.  
  649.     /**
  650.      * Sets the size of the split between panels and around the inside of the
  651.      * SplitterPanel border.
  652.      * The default for all gap sizes is 3.
  653.      * @param gapSize the split size in pixels
  654.      */
  655.     public void setGapSizes(int gapSize)
  656.     {
  657.         this.iGapWidth  = gapSize;
  658.         this.iGapHeight = gapSize;
  659.         this.oGapWidth  = gapSize;
  660.         this.oGapHeight = gapSize;
  661.         adjustOGapBdr();
  662.         propagateChanges();
  663.         repaint();
  664.     }
  665.  
  666.     /**
  667.      * Sets the size of the split between panels and around the inside of the
  668.      * SplitterPanel border.
  669.      * The default for all gap sizes is 3.
  670.      * @param gapWidth the split width in pixels
  671.      * @param gapHeight the split height in pixels
  672.      */
  673.     public void setGapSizes(int gapWidth, int gapHeight)
  674.     {
  675.         this.iGapWidth  = gapWidth;
  676.         this.iGapHeight = gapHeight;
  677.         this.oGapWidth  = gapWidth;
  678.         this.oGapHeight = gapHeight;
  679.         adjustOGapBdr();
  680.         propagateChanges();
  681.         repaint();
  682.     }
  683.  
  684.     /**
  685.      * Sets the size of the split between panels and around the inside of the
  686.      * SplitterPanel border.
  687.      * The default for all gap sizes is 3.
  688.      * @param iGapWidth the split width between panels, in pixels
  689.      * @param iGapHeight the split height between panels, in pixels
  690.      * @param oGapWidth the gap width inside the border, in pixels
  691.      * @param oGapHeight the gap height inside the border, in pixels
  692.      */
  693.     public void setGapSizes(int iGapWidth, int iGapHeight, int oGapWidth, int oGapHeight)
  694.     {
  695.         this.iGapWidth  = iGapWidth;
  696.         this.iGapHeight = iGapHeight;
  697.         this.oGapWidth  = oGapWidth;
  698.         this.oGapHeight = oGapHeight;
  699.         adjustOGapBdr();
  700.         propagateChanges();
  701.         repaint();
  702.     }
  703.  
  704.     /**
  705.      * Sets the size of the border drawn between panels and around the
  706.      * outside of the SplitterPanel.
  707.      * The default for all border sizes is 2.
  708.      * @param iBdrSize the border size between panels, in pixels
  709.      * @param oBdrSize the border size around the outside of the SplitterPanel, in pixels
  710.      */
  711.     public void setBdrSizes(int iBdrSize, int oBdrSize)
  712.     {
  713.         this.iBdrSize = iBdrSize;
  714.         this.oBdrSize = oBdrSize;
  715.         adjustOGapBdr();
  716.         propagateChanges();
  717.         repaint();
  718.     }
  719.  
  720.     /**
  721.      * Sets the size of the border drawn between panels and around the
  722.      * outside of the SplitterPanel.
  723.      * @param bdrSize the size in pixels
  724.      */
  725.     public void setBdrSizes(int bdrSize)
  726.     {
  727.         this.iBdrSize  = bdrSize;
  728.         this.oBdrSize  = bdrSize;
  729.         adjustOGapBdr();
  730.         propagateChanges();
  731.         repaint();
  732.     }
  733.  
  734.     /**
  735.      * Gets a panel within a SplitterPanel.
  736.      * @param n panel number (1 for first panel, or 2 for second
  737.      * panel)
  738.      * @return the panel, or null if none
  739.      * @see #getSub2Panel
  740.      */
  741.     public SplitterPanel getSubPanel(int n)
  742.     {
  743.         SplitterPanel targetSP = this;
  744.  
  745.         if (isOuter)
  746.             targetSP = this.innerSP;
  747.         if (n == 1)
  748.             return targetSP.sub1;
  749.         if (n == 2)
  750.             return targetSP.sub2;
  751.  
  752.         return null;
  753.     }
  754.  
  755.     /**
  756.      * Gets a panel within a SplitterPanel of specified type.
  757.      * For example, if "aPanel" was a horizontally split SplitterPanel,
  758.      * the call aPanel.getSubPanel(1,SPLIT_HOR) would retrieve the first
  759.      * (topmost) panel, and the call aPanel.getSubPanel(1,SPLIT_VER) would
  760.      * return null since aPanel is not split vertically.
  761.      *
  762.      * @param n panel number (1 for first panel, or 2 for second
  763.      * panel)
  764.      * @param theSplitType the type of split this panel has
  765.      * (SPLIT_VER or SPLIT_HOR)
  766.      * @return the panel, or null if none of the specified type
  767.      * @see #SPLIT_VER
  768.      * @see #SPLIT_HOR
  769.      * @see #getSub2Panel
  770.      */
  771.     public SplitterPanel getSubPanel(int n, int theSplitType)
  772.     {
  773.         if (getSplitType() == theSplitType)
  774.             return getSubPanel(n);
  775.  
  776.         return null;
  777.     }
  778.  
  779.     /**
  780.      * Gets a panel within a doubly split SplitterPanel with
  781.      * specified split types.
  782.      * This method is equivalent to calling getSubPanel() twice, the
  783.      * second time with the results from the first.
  784.      * @param n1 panel number (1 for first panel, or 2 for second panel)
  785.      * @param theSplitType1 the type of split this panel has
  786.      * (SPLIT_VER or SPLIT_HOR)
  787.      * @param n2 panel number (1 for first panel, or 2 for second panel)
  788.      * @param theSplitType2 the type of split the subpanel has
  789.      * (SPLIT_VER or SPLIT_HOR)
  790.      * @return the panel, or null if none of the specified type
  791.      * @see #SPLIT_VER
  792.      * @see #SPLIT_HOR
  793.      * @see #getSubPanel(int, int)
  794.      */
  795.     public SplitterPanel getSub2Panel(int n1, int theSplitType1, int n2, int theSplitType2)
  796.     {
  797.         SplitterPanel theSP;
  798.  
  799.         theSP = getSubPanel(n1, theSplitType1);
  800.         if (theSP != null)
  801.             return theSP.getSubPanel(n2, theSplitType2);
  802.  
  803.         return null;
  804.     }
  805.  
  806.     /**
  807.      * Gets the top panel of a horizontally split SplitterPanel.
  808.      * @return the panel, or null if this panel is not split or is
  809.      * split vertically
  810.      * @see #getBottomPanel
  811.      * @see #getLeftPanel
  812.      * @see #getRightPanel
  813.      * @see #getTopLeftPanel
  814.      * @see #getTopRightPanel
  815.      * @see #getBottomLeftPanel
  816.      * @see #getBottomRightPanel
  817.      */
  818.     public SplitterPanel getTopPanel()
  819.     {
  820.         return getSubPanel(1, SPLIT_HOR);
  821.     }
  822.  
  823.     /**
  824.      * Gets the bottom panel of a horizontally split SplitterPanel.
  825.      * @return the panel, or null if this panel is not split or is
  826.      * split vertically
  827.      * @see #getTopPanel
  828.      * @see #getLeftPanel
  829.      * @see #getRightPanel
  830.      * @see #getTopLeftPanel
  831.      * @see #getTopRightPanel
  832.      * @see #getBottomLeftPanel
  833.      * @see #getBottomRightPanel
  834.      */
  835.     public SplitterPanel getBottomPanel()
  836.     {
  837.         return getSubPanel(2, SPLIT_HOR);
  838.     }
  839.  
  840.     /**
  841.      * Gets the left panel of a vertically split SplitterPanel.
  842.      * @return the panel, or null if this panel is not split or is
  843.      * split horizontally
  844.      * @see #getTopPanel
  845.      * @see #getBottomPanel
  846.      * @see #getRightPanel
  847.      * @see #getTopLeftPanel
  848.      * @see #getTopRightPanel
  849.      * @see #getBottomLeftPanel
  850.      * @see #getBottomRightPanel
  851.      */
  852.     public SplitterPanel getLeftPanel()
  853.     {
  854.         return getSubPanel(1, SPLIT_VER);
  855.     }
  856.  
  857.     /**
  858.      * Gets the right panel of a vertically split SplitterPanel.
  859.      * @return the panel, or null if this panel is not split or is
  860.      * split horizontally
  861.      * @see #getTopPanel
  862.      * @see #getBottomPanel
  863.      * @see #getLeftPanel
  864.      * @see #getTopLeftPanel
  865.      * @see #getTopRightPanel
  866.      * @see #getBottomLeftPanel
  867.      * @see #getBottomRightPanel
  868.      */
  869.     public SplitterPanel getRightPanel()
  870.     {
  871.         return getSubPanel(2, SPLIT_VER);
  872.     }
  873.  
  874.     /**
  875.      * Gets the top left panel.
  876.      * It doesn't matter if this SplitterPanel is initially split horizontally
  877.      * or vertically.
  878.      * @return the panel, or null if it doesn't exist
  879.      * @see #getTopPanel
  880.      * @see #getBottomPanel
  881.      * @see #getLeftPanel
  882.      * @see #getRightPanel
  883.      * @see #getTopRightPanel
  884.      * @see #getBottomLeftPanel
  885.      * @see #getBottomRightPanel
  886.      */
  887.     public SplitterPanel getTopLeftPanel()
  888.     {
  889.         if (getSplitType() == SPLIT_HOR)
  890.             return getSub2Panel(1, SPLIT_HOR, 1, SPLIT_VER);
  891.  
  892.         return getSub2Panel(1, SPLIT_VER, 1, SPLIT_HOR);
  893.     }
  894.  
  895.     /**
  896.      * Gets the top right panel.
  897.      * It doesn't matter if this SplitterPanel is initially split horizontally
  898.      * or vertically.
  899.      * @return the panel, or null if it doesn't exist
  900.      * @see #getTopPanel
  901.      * @see #getBottomPanel
  902.      * @see #getLeftPanel
  903.      * @see #getRightPanel
  904.      * @see #getTopLeftPanel
  905.      * @see #getBottomLeftPanel
  906.      * @see #getBottomRightPanel
  907.      */
  908.     public SplitterPanel getTopRightPanel()
  909.     {
  910.         if (getSplitType() == SPLIT_HOR)
  911.             return getSub2Panel(1, SPLIT_HOR, 2, SPLIT_VER);
  912.  
  913.         return getSub2Panel(2, SPLIT_VER, 1, SPLIT_HOR);
  914.     }
  915.  
  916.     /**
  917.      * Gets the bottom left panel.
  918.      * It doesn't matter if this SplitterPanel is initially split horizontally
  919.      * or vertically.
  920.      * @return the panel, or null if it doesn't exist
  921.      * @see #getTopPanel
  922.      * @see #getBottomPanel
  923.      * @see #getLeftPanel
  924.      * @see #getRightPanel
  925.      * @see #getTopLeftPanel
  926.      * @see #getTopRightPanel
  927.      * @see #getBottomRightPanel
  928.      */
  929.     public SplitterPanel getBottomLeftPanel()
  930.     {
  931.         if (getSplitType() == SPLIT_HOR)
  932.             return getSub2Panel(2, SPLIT_HOR, 1, SPLIT_VER);
  933.  
  934.         return getSub2Panel(1, SPLIT_VER, 2, SPLIT_HOR);
  935.     }
  936.  
  937.     /**
  938.      * Gets the bottom right panel.
  939.      * It doesn't matter if this SplitterPanel is initially split horizontally
  940.      * or vertically.
  941.      * @return the panel, or null if it doesn't exist
  942.      * @see #getTopPanel
  943.      * @see #getBottomPanel
  944.      * @see #getLeftPanel
  945.      * @see #getRightPanel
  946.      * @see #getTopLeftPanel
  947.      * @see #getTopRightPanel
  948.      * @see #getBottomLeftPanel
  949.      */
  950.     public SplitterPanel getBottomRightPanel()
  951.     {
  952.         if (getSplitType() == SPLIT_HOR)
  953.             return getSub2Panel(2, SPLIT_HOR, 2, SPLIT_VER);
  954.  
  955.         return getSub2Panel(2, SPLIT_VER, 2, SPLIT_HOR);
  956.     }
  957.  
  958.     /**
  959.      * Gets the size of the split between panels.
  960.      * @return the split width between panels, in pixels
  961.      * @see #iGapHeight()
  962.      * @see #oGapWidth()
  963.      * @see #oGapHeight()
  964.      */
  965.     public int iGapWidth()
  966.     {
  967.         return this.iGapWidth;
  968.     }
  969.  
  970.     /**
  971.      * Gets the size of the split between panels.
  972.      * @return the split height between panels, in pixels
  973.      * @see #iGapWidth()
  974.      * @see #oGapWidth()
  975.      * @see #oGapHeight()
  976.      */
  977.     public int iGapHeight()
  978.     {
  979.         return this.iGapHeight;
  980.     }
  981.  
  982.     /**
  983.      * Gets the size of the split around the inside of the SplitterPanel border.
  984.      * @return the gap width inside the border, in pixels
  985.      * @see #iGapWidth()
  986.      * @see #iGapHeight()
  987.      * @see #oGapHeight()
  988.      */
  989.     public int oGapWidth()
  990.     {
  991.         return this.oGapWidth;
  992.     }
  993.  
  994.     /**
  995.      * Gets the size of the split around the inside of the SplitterPanel border.
  996.      * @return the gap height inside the border, in pixels
  997.      * @see #iGapWidth()
  998.      * @see #iGapHeight()
  999.      * @see #oGapWidth()
  1000.      */
  1001.     public int oGapHeight()
  1002.     {
  1003.         return this.oGapHeight;
  1004.     }
  1005.  
  1006.     /**
  1007.      * Gets the size of the border drawn between panels.
  1008.      * @return the border size between panels, in pixels
  1009.      * @see #oBdrSize()
  1010.      */
  1011.     public int iBdrSize()
  1012.     {
  1013.         return this.iBdrSize;
  1014.     }
  1015.  
  1016.     /**
  1017.      * Gets the size of the border drawn around the outside of the SplitterPanel.
  1018.      * @return the border size around the outside of the SplitterPanel, in pixels
  1019.      * @see #iBdrSize()
  1020.      */
  1021.     public int oBdrSize()
  1022.     {
  1023.         return this.oBdrSize;
  1024.     }
  1025.  
  1026.     /**
  1027.      * Handles the laying out of components within this component.
  1028.      * This is a standard Java AWT method which gets called by the AWT
  1029.      * when this component is validated with the validate() method.
  1030.      *
  1031.      * @see java.awt.Container#validate
  1032.      */
  1033.     public synchronized void layout()
  1034.     {
  1035.       placeComponents();
  1036.     }
  1037.  
  1038.     /**
  1039.      * Moves the location of the gap between panels.
  1040.      * @param spX specifies relative movement in pixels along horizontal axis
  1041.      * @param spY specifies relative movement in pixels along vertical axis
  1042.      */
  1043.     public void moveSplit(int spX, int spY)
  1044.     {
  1045.         Rectangle cur1;
  1046.         Rectangle cur2;
  1047.         Dimension min1;
  1048.         Dimension min2;
  1049.  
  1050.         int delta;
  1051.         int newX1;
  1052.         int newY1;
  1053.         int newWidth1;
  1054.         int newHeight1;
  1055.         int newX2;
  1056.         int newY2;
  1057.         int newWidth2;
  1058.         int newHeight2;
  1059.  
  1060.         if (isOuter)
  1061.         {
  1062.             innerSP.moveSplit(spX, spY);
  1063.             return;
  1064.         }
  1065.         else
  1066.         {
  1067.             min1 = sub1.minimumSize();
  1068.             min2 = sub2.minimumSize();
  1069.             cur1 = new Rectangle(sub1.curLoc.x, sub1.curLoc.y, sub1.curDim.width, sub1.curDim.height);
  1070.             cur2 = new Rectangle(sub2.curLoc.x, sub2.curLoc.y, sub2.curDim.width, sub2.curDim.height);
  1071.             newX1 = cur1.x;
  1072.             newY1 = cur1.y;
  1073.  
  1074.             if (splitType == SPLIT_HOR)
  1075.             {
  1076.                 if (spY == 0) return;
  1077.                 if (spY > 0)
  1078.                 {
  1079.                     if (enforceMinDim)
  1080.                     {
  1081.                          newHeight2 = Math.max(cur2.height - spY, min2.height);
  1082.                     }
  1083.                     else
  1084.                     {
  1085.                          newHeight2 = Math.max(cur2.height - spY, 2*iBdrSize);
  1086.                     }
  1087.                     newHeight1 = cur1.height + cur2.height - newHeight2;
  1088.                 }
  1089.                 else
  1090.                 {
  1091.                     if (enforceMinDim)
  1092.                     {
  1093.                          newHeight1 = Math.max(cur1.height + spY, min1.height);
  1094.                     }
  1095.                     else
  1096.                     {
  1097.                          newHeight1 = Math.max(cur1.height + spY, 2*iBdrSize);
  1098.                     }
  1099.                     newHeight2 = cur2.height + cur1.height - newHeight1;
  1100.                 }
  1101.                 newWidth1 = cur1.width;
  1102.                 newWidth2 = cur2.width;
  1103.                 newX2 = cur2.x;
  1104.                 newY2 = cur2.y - cur1.height + newHeight1;
  1105.                 sub1.reshapeHeight(newY1, newHeight1);
  1106.                 sub2.reshapeHeight(newY2, newHeight2);
  1107.             }
  1108.  
  1109.             if (splitType == SPLIT_VER)
  1110.             {
  1111.                 if (spX == 0) return;
  1112.                 if (spX > 0)
  1113.                 {
  1114.                     if (enforceMinDim)
  1115.                     {
  1116.                          newWidth2 = Math.max(cur2.width - spX, min2.width);
  1117.                     }
  1118.                     else
  1119.                     {
  1120.                          newWidth2 = Math.max(cur2.width - spX, 2*iBdrSize);
  1121.                     }
  1122.                     newWidth1 = cur1.width + cur2.width - newWidth2;
  1123.  
  1124.                 }
  1125.                 else
  1126.                 {
  1127.                     if (enforceMinDim)
  1128.                     {
  1129.                          newWidth1 = Math.max(cur1.width + spX, min1.width);
  1130.                     }
  1131.                     else
  1132.                     {
  1133.                          newWidth1 = Math.max(cur1.width + spX, 1*iBdrSize);
  1134.                     }
  1135.                     newWidth2 = cur2.width + cur1.width - newWidth1;
  1136.  
  1137.                 }
  1138.                 newHeight1 = cur1.height;
  1139.                 newHeight2 = cur2.height;
  1140.                 newY2 = cur2.y;
  1141.                 newX2 = cur2.x - cur1.width + newWidth1;
  1142.                 sub1.reshapeWidth(newX1, newWidth1);
  1143.                 sub2.reshapeWidth(newX2, newWidth2);
  1144.             }
  1145.  
  1146.             sub1.invalidate();
  1147.             sub1.validate();
  1148.             sub1.repaint();
  1149.             sub2.invalidate();
  1150.             sub2.validate();
  1151.             sub2.repaint();
  1152.         }
  1153.     }
  1154.  
  1155.     /**
  1156.      * Handles redrawing of this component on the screen.
  1157.      * This is a standard Java AWT method which gets called by the Java
  1158.      * AWT (repaint()) to handle repainting this component on the screen.
  1159.      * The graphics context clipping region is set to the bounding rectangle
  1160.      * of this component and its [0,0] coordinate is this component's
  1161.      * top-left corner.
  1162.      * Typically this method paints the background color to clear the
  1163.      * component's drawing space, sets graphics context to be the foreground
  1164.      * color, and then calls paint() to draw the component.
  1165.      *
  1166.      * It is overridden here to reduce flicker by eliminating the unnecessary
  1167.      * clearing of the background.
  1168.      *
  1169.      * @param g the graphics context
  1170.      * @see java.awt.Component#repaint
  1171.      * @see #paint
  1172.      */
  1173.     public void update(Graphics g)
  1174.     {
  1175.         paint(g);
  1176.     }
  1177.  
  1178.     /**
  1179.      * Paints this component using the given graphics context.
  1180.      * This is a standard Java AWT method which typically gets called
  1181.      * by the AWT to handle painting this component. It paints this component
  1182.      * using the given graphics context. The graphics context clipping region
  1183.      * is set to the bounding rectangle of this component and its [0,0]
  1184.      * coordinate is this component's top-left corner.
  1185.      *
  1186.      * Overriding this method is not advised.
  1187.      *
  1188.      * @param g the graphics context used for painting
  1189.      * @see java.awt.Component#repaint
  1190.      * @see #update
  1191.      */
  1192.     public void paint(Graphics g)
  1193.     {
  1194.         Color bgColor;
  1195.         Color fgColor;
  1196.  
  1197.         Dimension d = size();
  1198.  
  1199.         bgColor = getBackground();
  1200.         g.setColor(bgColor);
  1201.  
  1202.         if (isOuter)
  1203.         {
  1204.             g.setColor(gapColor);
  1205.             g.fillRect(0, 0, d.width, d.height);
  1206.             draw3DBdr(g, 0, 0, d.width-1, d.height-1, oBdrSize, gapColor, true);
  1207.         }
  1208.         else if (splitType == SPLIT_NONE)
  1209.         {
  1210.             g.setColor(bgColor);
  1211.             g.fillRect(0, 0, d.width, d.height );
  1212.             draw3DBdr(g, 0, 0, d.width-1, d.height-1, iBdrSize, gapColor, false);
  1213.         }
  1214.         else
  1215.         {
  1216.             g.setColor(gapColor);
  1217.             g.fillRect(0, 0, d.width, d.height );
  1218.         }
  1219.  
  1220.         super.paint(g);
  1221.     }
  1222.  
  1223.  
  1224.     /**
  1225.      * Gets the component in this SplitterPanel.
  1226.      * @return the component in this SplitterPanel
  1227.      */
  1228.     public Component getComponent()
  1229.     {
  1230.         if (isOuter)
  1231.             return innerSP.getComponent();
  1232.  
  1233.         return spComponent;
  1234.     }
  1235.  
  1236.     /**
  1237.      * Returns all of the components in this container.
  1238.      * This is a standard Java AWT method which gets called to return
  1239.      * an array of all of the components in this container.
  1240.      *
  1241.      * @return an array of components in this container
  1242.      */
  1243.     public Component[] getComponents()
  1244.     {
  1245.         if (isOuter)
  1246.             return innerSP.getComponents();
  1247.  
  1248.         return super.getComponents();
  1249.  
  1250.     }
  1251.  
  1252.     /**
  1253.      * Returns number of components in this container.
  1254.      *
  1255.      * @return the number of components in this container
  1256.      */
  1257.     public int getComponentCount()
  1258.     {
  1259.         if (isOuter)
  1260.             return innerSP.getComponentCount();
  1261.  
  1262.         return super.getComponentCount();
  1263.  
  1264.     }
  1265.  
  1266.     /**
  1267.      * Returns the recommended dimensions to properly display this component.
  1268.      * This is a standard Java AWT method which gets called to determine
  1269.      * the recommended size of this component.
  1270.      * <p>
  1271.      * For each axis, returns the larger of the actual size needed to show all
  1272.      * the components at their preferred size, and the preferred size set by
  1273.      * the setPreferredSize() method.
  1274.      *
  1275.      * @see #minimumSize
  1276.      * @see #setPreferredSize
  1277.      */
  1278.     public Dimension preferredSize()
  1279.     {
  1280.         Dimension p = size();
  1281.         Dimension m = getMinimumSize();
  1282.         return new Dimension(Math.max(p.width, m.width), Math.max(p.height, m.height));
  1283.     }
  1284.  
  1285.     /**
  1286.      * Returns the minimum dimensions to properly display this component.
  1287.      * This is a standard Java AWT method which gets called to determine
  1288.      * the minimum size of this component.
  1289.      * <p>
  1290.      * For each axis, returns the larger of the actual size needed to show all
  1291.      * the components at their minimum size, and the minimum size set by
  1292.      * the setMinimumSize() method.
  1293.      *
  1294.      * @see #preferredSize
  1295.      */
  1296.     public Dimension minimumSize()
  1297.     {
  1298.         Dimension theDim;
  1299.  
  1300.         if (isOuter)
  1301.         {
  1302.             theDim = new Dimension(innerSP.minimumSize());
  1303.             theDim.width  += 2*(oGapWidth  + oBdrSize);
  1304.             theDim.height += 2*(oGapHeight + oBdrSize);
  1305.         }
  1306.         else
  1307.         {
  1308.             if (splitType == SPLIT_NONE)
  1309.             {
  1310.                 if (spComponent == null)
  1311.                 {
  1312.                     theDim = new Dimension(0, 0);
  1313.                 }
  1314.                 else
  1315.                 {
  1316.                     theDim = new Dimension(spComponent.minimumSize());
  1317.                 }
  1318.                 theDim.width  += 2*(iBdrSize);
  1319.                 theDim.height += 2*(iBdrSize);
  1320.             }
  1321.             else
  1322.             {
  1323.                 Dimension theDim1;
  1324.                 Dimension theDim2;
  1325.  
  1326.                 theDim1 = sub1.minimumSize();
  1327.                 theDim2 = sub2.minimumSize();
  1328.  
  1329.                 if (splitType == SPLIT_HOR)
  1330.                 {
  1331.                     theDim = new Dimension(theDim1.width, theDim1.height + theDim2.height);
  1332.                     theDim.height += iGapHeight;
  1333.                 }
  1334.                 else
  1335.                 {
  1336.                     theDim = new Dimension(theDim1.width + theDim1.width, theDim1.height);
  1337.                     theDim.width  += iGapWidth;
  1338.                 }
  1339.             }
  1340.         }
  1341.  
  1342.         return maxDimOf(minDim, theDim);
  1343.     }
  1344.  
  1345.     /**
  1346.      * Sets the preferred size of this SplitterPanel.
  1347.      * This will override the calculated preferred size when the calculated
  1348.      * size is smaller.
  1349.      * @param theDim the preferred dimensions
  1350.      */
  1351.     public void setPreferredSize(Dimension theDim)
  1352.     {
  1353.         prefDim.width  = theDim.width;
  1354.         prefDim.height = theDim.height;
  1355.         //Must ensure that preferred size is as big as minimum size
  1356.         prefDim = maxDimOf(theDim, prefDim);
  1357.         layout();
  1358.     }
  1359.  
  1360.     /**
  1361.      * Sets the minimum size of this SplitterPanel.
  1362.      * This will override the calculated minimum size when the calculated
  1363.      * size is smaller.
  1364.      * @param theDim the minimum dimensions
  1365.      */
  1366.     public void setMinimumSize(Dimension theDim)
  1367.     {
  1368.         minDim.width  = theDim.width;
  1369.         minDim.height = theDim.height;
  1370.         prefDim = maxDimOf(theDim, prefDim);
  1371.         layout();
  1372.     }
  1373.  
  1374.     /**
  1375.      * Moves and/or resizes this component.
  1376.      * This is a standard Java AWT method which gets called to move and/or
  1377.      * resize this component. Components that are in containers with layout
  1378.      * managers should not call this method, but rely on the layout manager
  1379.      * instead.
  1380.      *
  1381.      * @param x horizontal position in the parent's coordinate space
  1382.      * @param y vertical position in the parent's coordinate space
  1383.      * @param width the new width
  1384.      * @param height the new height
  1385.      * @see #reshapeHeight
  1386.      * @see #reshapeWidth
  1387.      */
  1388.     public synchronized void reshape (int x, int y, int width, int height) {
  1389.         super.reshape(x, y, width, height);
  1390.         if ((curDim.width  != width) || (curDim.height != height) ||
  1391.             (curLoc.x != x) || (curLoc.y != y))
  1392.         {
  1393.             layout();
  1394.             curDim.width  = width;
  1395.             curDim.height = height;
  1396.             curLoc.x      = x;
  1397.             curLoc.y      = y;
  1398.         }
  1399.     }
  1400.  
  1401.     /**
  1402.      * Reshapes the width and/or horizontal position.
  1403.      * This prevents vertical adjustments when the layout is computed.
  1404.      * @param x horizontal position in the parent's coordinate space
  1405.      * @param width the new width, in pixels
  1406.      * @see #reshapeHeight
  1407.      * @see #reshape
  1408.      */
  1409.     public synchronized void reshapeWidth(int x, int width) {
  1410.         Rectangle rect = new Rectangle(curLoc.x, curLoc.y, curDim.width, curDim.height);
  1411.  
  1412.         if (curDim.width  != width)
  1413.         {
  1414.             widthOnly = true;
  1415.             curDim.width  = width;
  1416.         }
  1417.         reshape(x, rect.y, width, rect.height);
  1418.     }
  1419.  
  1420.     /**
  1421.      * Reshapes the height and/or vertical position.
  1422.      * This prevents horizontal adjustments when the layout is computed.
  1423.      * @param y vertical position in the parent's coordinate space
  1424.      * @param height the new height, in pixels
  1425.      * @see #reshapeWidth
  1426.      * @see #reshape
  1427.      */
  1428.     public synchronized void reshapeHeight(int y, int height) {
  1429.         Rectangle rect = new Rectangle(curLoc.x, curLoc.y, curDim.width, curDim.height);
  1430.  
  1431.         if (curDim.height != height)
  1432.         {
  1433.             heightOnly = true;
  1434.             curDim.height = height;
  1435.         }
  1436.         reshape(rect.x, y, rect.width, height);
  1437.     }
  1438.  
  1439.     /**
  1440.      * Adds a component to the end of this container.
  1441.      * This is a standard Java AWT method which gets called to add a
  1442.      * component to a container. Typically, the specified component is added to
  1443.      * this container at the given zero-relative position index. A
  1444.      * position index of -1 would append the component to the end.
  1445.      *
  1446.      * It is overridden here to set the only
  1447.      * component in this SplitterPanel. This is the component that is displayed
  1448.      * in a panel. The SplitterPanel can only contain one component.
  1449.      * Any previous component will be removed before the new one is added.
  1450.      *
  1451.      * @param comp the component to add
  1452.      * @param pos the zero-relative index at which to add the component or -1
  1453.      * for end (IGNORED)
  1454.      * @return the added component
  1455.      * @see #remove
  1456.      */
  1457.     public synchronized Component add(Component comp, int pos)
  1458.     {
  1459.         if (comp == null)
  1460.             return null;
  1461.  
  1462.         if (isOuter)
  1463.             return innerSP.add(comp, pos);
  1464.  
  1465.         if (spComponent != null)
  1466.             super.remove(spComponent);
  1467.  
  1468.         spComponent = super.add(comp, -1);
  1469.         layout();
  1470.  
  1471.         return spComponent;
  1472.     }
  1473.  
  1474.     /**
  1475.      * Adds a component to the end of this container.
  1476.      * This is a standard Java AWT method which gets called to add a
  1477.      * component to a container. Typically, the specified component is added to
  1478.      * the end of this container.
  1479.      *
  1480.      * It is overridden here to set the only
  1481.      * component in this SplitterPanel. This is the component that is displayed
  1482.      * in a panel. The SplitterPanel can only contain one component.
  1483.      * Any previous component will be removed before the new one is added.
  1484.      *
  1485.      * @param comp the component to add
  1486.      * @return the added component
  1487.      * @see #remove
  1488.      */
  1489.     public Component add(Component comp) {
  1490.         return this.add(comp, -1);
  1491.     }
  1492.  
  1493.     /**
  1494.      * Removes the specified component from this container.
  1495.      * This is a standard Java AWT method which gets called to remove a
  1496.      * component from a container. When this happens the component's
  1497.      * removeNotify() will also get called to indicate component removal.
  1498.      *
  1499.      * @param comp the component to remove
  1500.      * @see #removeAll
  1501.      * @see #add
  1502.      */
  1503.     public synchronized void remove(Component comp)
  1504.     {
  1505.         if (isOuter)
  1506.         {
  1507.             innerSP.remove(comp);
  1508.         }
  1509.         else
  1510.         {
  1511.             if (comp == spComponent)
  1512.             {
  1513.                 spComponent = null;
  1514.                 super.remove(comp);
  1515.             }
  1516.             else
  1517.             {
  1518.                 if (sub1 != null)
  1519.                     sub1.remove(comp);
  1520.  
  1521.                 if (sub2 != null)
  1522.                     sub2.remove(comp);
  1523.             }
  1524.         }
  1525.     }
  1526.  
  1527.     /**
  1528.      * Removes all the components from this container.
  1529.      * This is a standard Java AWT method which gets called to remove all
  1530.      * the components from a container. When this happens each component's
  1531.      * removeNotify() will also get called to indicate component removal.
  1532.      * <p>
  1533.      * Split panels are preserved.
  1534.      *
  1535.      * @see #remove
  1536.      * @see #add
  1537.      */
  1538.     public synchronized void removeAll()
  1539.     {
  1540.         if (isOuter)
  1541.         {
  1542.             innerSP.removeAll();
  1543.         }
  1544.  
  1545.         else
  1546.         {
  1547.             super.removeAll();
  1548.  
  1549.             if (sub1 != null)
  1550.             {
  1551.                 super.add(sub1, -1);
  1552.                 sub1.removeAll();
  1553.             }
  1554.  
  1555.             if (sub2 != null)
  1556.             {
  1557.                 super.add(sub2, -1);
  1558.                 sub1.removeAll();
  1559.             }
  1560.         }
  1561.  
  1562.         spComponent = null;
  1563.     }
  1564.  
  1565.     /**
  1566.      * Splits a SplitterPanel into two panels.
  1567.      * This creates two new SplitterPanels which are nested within the original
  1568.      * SplitterPanel. If the split type is SPLIT_VER the new panels are arranged
  1569.      * side-by-side with a splitter bar vertically between them.
  1570.      * If the split type is SPLIT_HOR the new panels are arranged one above the
  1571.      * other with a splitter bar horizontally between them.
  1572.      *
  1573.      * @param splitType SPLIT_VER or SPLIT_HOR to request a
  1574.      * vertical or horizontal split
  1575.      * @return the first new SplitterPanel if successful (left or top)
  1576.      * @see #SPLIT_VER
  1577.      * @see #SPLIT_HOR
  1578.      */
  1579.     public SplitterPanel split(int splitType)
  1580.     {
  1581.         return split(splitType, null, null);
  1582.     }
  1583.  
  1584.     /**
  1585.      * Splits a SplitterPanel into two panels and adds two components.
  1586.      * This creates two new SplitterPanels which are nested within the original
  1587.      * SplitterPanel.
  1588.      * <p>
  1589.      * If the split type is SPLIT_VER the new panels are arranged
  1590.      * side-by-side with a splitter bar vertically between them.
  1591.      * Component theComp1 would be placed in the left panel, theComp2 in the right.
  1592.      * <p>
  1593.      * If the split type is SPLIT_HOR the new panels are arranged one above the
  1594.      * other with a splitter bar horizontally between them.
  1595.      * Component theComp1 would be placed in the top panel, theComp2 in the bottom.
  1596.      *
  1597.      * @param splitType SPLIT_VER or SPLIT_HOR to request
  1598.      * vertical or horizontal splits
  1599.      * @param theComp1 the first component (left or top)
  1600.      * @param theComp2 the second component (right or bottom)
  1601.      * @return the first new SplitterPanel if successful (left or top)
  1602.      * @see #SPLIT_VER
  1603.      * @see #SPLIT_HOR
  1604.      */
  1605.     public synchronized SplitterPanel split(int splitType, Component theComp1, Component theComp2)
  1606.     {
  1607.         if (isOuter)
  1608.             return(this.innerSP.split(splitType, theComp1, theComp2));
  1609.  
  1610.         if (this.splitType != SPLIT_NONE)
  1611.             return null;
  1612.  
  1613.         if ((splitType != SPLIT_VER) && (splitType != SPLIT_HOR))
  1614.             return null;
  1615.  
  1616.         sub1 = new SplitterPanel(false);
  1617.         if (sub1 == null)
  1618.             return null;
  1619.  
  1620.         sub2 = new SplitterPanel(false);
  1621.         if (sub2 == null)
  1622.         {
  1623.             super.remove(sub1);
  1624.             return null;
  1625.         }
  1626.  
  1627.         this.splitType = splitType;
  1628.  
  1629.         sub1.outerSP = this.outerSP;
  1630.         sub2.outerSP = this.outerSP;
  1631.  
  1632.         super.add(sub1, -1);
  1633.         super.add(sub2, -1);
  1634.  
  1635.         if (theComp1 != null)
  1636.             sub1.add(theComp1);
  1637.  
  1638.         if (theComp2 != null)
  1639.             sub2.add(theComp2);
  1640.  
  1641.         propagateChanges();
  1642.         return sub1;
  1643.     }
  1644.  
  1645.     /**
  1646.      * Takes no action.
  1647.      * This is a standard Java AWT method which gets called to specify
  1648.      * which layout manager should be used to layout the components in
  1649.      * standard containers.
  1650.      *
  1651.      * Since layout managers CANNOT BE USED with this container the standard
  1652.      * setLayout has been OVERRIDDEN for this container and does nothing.
  1653.      *
  1654.      * @param l the layout manager to use to layout this container's components
  1655.      * (IGNORED)
  1656.      * @see java.awt.Container#getLayout
  1657.      **/
  1658.     public void setLayout(LayoutManager mgr)
  1659.     {
  1660.     }
  1661.  
  1662.     /**
  1663.      * Override this method if you want a behavior when events
  1664.      * occur in the outer gap.  Be sure to call super.oGapThis
  1665.      * if you do override this method.  Note that it is recommended
  1666.      * that you place a SplitterPanel inside of a frame and set
  1667.      * outer border and gap sizes to zero if you want the end user
  1668.      * to be able to resize.
  1669.      * @param x the x coordinate of where the event occured.
  1670.      * @param y the y coordinate of where the event occured.
  1671.      */
  1672.     public void oGapThis(int x, int y)
  1673.     {
  1674.         if (!doMoveSplit && !inGap(x, y))
  1675.             resetCursor();
  1676.     }
  1677.  
  1678.     /**
  1679.      * @deprecated
  1680.      * @see #oGapThis(int, int)
  1681.      */
  1682.     public boolean oGapThis(Event evt)
  1683.     {
  1684.         oGapThis(evt.x, evt.y);
  1685.         return true;
  1686.     }
  1687.  
  1688.     /**
  1689.      * Returns a string representation of this component.
  1690.      * This is a standard Java AWT method which gets called to generate
  1691.      * a string that represents this component.
  1692.      *
  1693.      * @return a meaningful string about this object
  1694.      */
  1695.     public String toString()
  1696.     {
  1697.         String typeString = "Bad Panel ";
  1698.         Container theParent;
  1699.         String theParentString;
  1700.  
  1701.         if (isOuter)
  1702.         {
  1703.             typeString = "Outer ";
  1704.         }
  1705.         else
  1706.         {
  1707.             if (splitType == SPLIT_NONE)
  1708.             {
  1709.                 typeString = "Unsplit ";
  1710.             }
  1711.             if (splitType == SPLIT_VER)
  1712.             {
  1713.                 typeString = "Vertically split ";
  1714.             }
  1715.             if (splitType == SPLIT_HOR)
  1716.             {
  1717.                 typeString = "Horizontally split ";
  1718.             }
  1719.         }
  1720.  
  1721.         theParent = getParent();
  1722.         if (theParent == null)
  1723.             theParentString = " with no parent (not added)";
  1724.  
  1725.         else
  1726.             theParentString = " with parent @" + theParent.hashCode();
  1727.  
  1728.         return typeString + super.toString() + ": @"  + hashCode() +  theParentString;
  1729.     }
  1730.  
  1731.     /**
  1732.      * Tells this component that it has been added to a container.
  1733.      * This is a standard Java AWT method which gets called by the AWT when
  1734.      * this component is added to a container. Typically, it is used to
  1735.      * create this component's peer.
  1736.      *
  1737.      * It has been overridden here to hook-up event listeners.
  1738.      *
  1739.      * @see #removeNotify
  1740.      */
  1741.     public synchronized void addNotify()
  1742.     {
  1743.         super.addNotify();
  1744.         errors = ResourceBundle.getBundle("symantec.itools.resources.ErrorsBundle");
  1745.  
  1746.         //Hook up listeners
  1747.         if (mouse == null)
  1748.         {
  1749.             mouse = new Mouse();
  1750.             addMouseListener(mouse);
  1751.         }
  1752.         if (mouseMotion == null)
  1753.         {
  1754.             mouseMotion = new MouseMtn();
  1755.             addMouseMotionListener(mouseMotion);
  1756.         }
  1757.         if (stVeto == null)
  1758.         {
  1759.             stVeto = new STVeto();
  1760.             addSplitTypeListener(stVeto);
  1761.         }
  1762.     }
  1763.  
  1764.     /**
  1765.      * Tells this component that it is being removed from a container.
  1766.      * This is a standard Java AWT method which gets called by the AWT when
  1767.      * this component is removed from a container. Typically, it is used to
  1768.      * destroy the peers of this component and all its subcomponents.
  1769.      *
  1770.      * It has been overridden here to unhook event listeners.
  1771.      *
  1772.      * @see #addNotify
  1773.      */
  1774.     public synchronized void removeNotify()
  1775.     {
  1776.         //Unhook listeners
  1777.         if (mouse != null)
  1778.         {
  1779.             removeMouseListener(mouse);
  1780.             mouse = null;
  1781.         }
  1782.         if (mouseMotion != null)
  1783.         {
  1784.             removeMouseMotionListener(mouseMotion);
  1785.             mouseMotion = null;
  1786.         }
  1787.         if (stVeto != null)
  1788.         {
  1789.             removeSplitTypeListener(stVeto);
  1790.             stVeto = null;
  1791.         }
  1792.  
  1793.         super.removeNotify();
  1794.     }
  1795.  
  1796.     /**
  1797.      * Checks to see if a given SplitType is a valid split type.
  1798.      * @param testSplitType the split type to test
  1799.      * @return true if testSplitType is acceptable, false if not.
  1800.      */
  1801.     public boolean isValidSplitType(int testSplitType)
  1802.     {
  1803.         switch(testSplitType)
  1804.         {
  1805.             case SPLIT_NONE:
  1806.             case SPLIT_VERTICAL:
  1807.             case SPLIT_HORIZONTAL:
  1808.                 return true;
  1809.             default:
  1810.                 return false;
  1811.         }
  1812.     }
  1813.  
  1814.     /**
  1815.      * Adds a listener for all event changes.
  1816.      * @param listener the listener to add.
  1817.      * @see #removePropertyChangeListener
  1818.      */
  1819.     public synchronized void addPropertyChangeListener(PropertyChangeListener listener)
  1820.     {
  1821.         changes.addPropertyChangeListener(listener);
  1822.     }
  1823.  
  1824.     /**
  1825.      * Removes a listener for all event changes.
  1826.      * @param listener the listener to remove.
  1827.      * @see #addPropertyChangeListener
  1828.      */
  1829.     public synchronized void removePropertyChangeListener(PropertyChangeListener listener)
  1830.     {
  1831.         changes.removePropertyChangeListener(listener);
  1832.     }
  1833.  
  1834.     /**
  1835.      * Adds a vetoable listener for all event changes.
  1836.      * @param listener the listener to add.
  1837.      * @see #removeVetoableChangeListener
  1838.      */
  1839.     public synchronized void addVetoableChangeListener(VetoableChangeListener listener)
  1840.     {
  1841.         vetos.addVetoableChangeListener(listener);
  1842.     }
  1843.  
  1844.     /**
  1845.      * Removes a vetoable listener for all event changes.
  1846.      * @param listener the listener to remove.
  1847.      * @see #addVetoableChangeListener
  1848.      */
  1849.     public synchronized void removeVetoableChangeListener(VetoableChangeListener listener)
  1850.     {
  1851.         vetos.removeVetoableChangeListener(listener);
  1852.     }
  1853.  
  1854.     /**
  1855.      * Adds a property listener for SplitType changes.
  1856.      * @param listener the listener to add.
  1857.      * @see #removeSplitTypeListener
  1858.      */
  1859.     public synchronized void addSplitTypeListener(PropertyChangeListener listener)
  1860.     {
  1861.         changes.addPropertyChangeListener("SplitType", listener);
  1862.     }
  1863.  
  1864.     /**
  1865.      * Removes a property listener for SplitType changes.
  1866.      * @param listener the listener to remove.
  1867.      * @see #addSplitTypeListener
  1868.      */
  1869.     public synchronized void removeSplitTypeListener(PropertyChangeListener listener)
  1870.     {
  1871.         changes.removePropertyChangeListener("SplitType", listener);
  1872.     }
  1873.  
  1874.     /**
  1875.      * Adds a vetoable listener for SplitType changes.
  1876.      * @param listener the listener to add.
  1877.      * @see #removeSplitTypeListener
  1878.      */
  1879.     public synchronized void addSplitTypeListener(VetoableChangeListener listener)
  1880.     {
  1881.         vetos.addVetoableChangeListener("SplitType", listener);
  1882.     }
  1883.  
  1884.     /**
  1885.      * Removes a vetoable listener for SplitType changes.
  1886.      * @param listener the listener to remove.
  1887.      * @see #addSplitTypeListener
  1888.      */
  1889.     public synchronized void removeSplitTypeListener(VetoableChangeListener listener)
  1890.     {
  1891.         vetos.removeVetoableChangeListener("SplitType", listener);
  1892.     }
  1893.  
  1894.     /**
  1895.      * This is the Mouse Event handling innerclass.
  1896.      */
  1897.     class Mouse extends java.awt.event.MouseAdapter implements java.io.Serializable
  1898.     {
  1899.         /**
  1900.          * Handles Mouse Pressed events
  1901.          * @param e the MouseEvent
  1902.          */
  1903.         public void mousePressed(MouseEvent e)
  1904.         {
  1905.             int x = e.getX();
  1906.             int y = e.getY();
  1907.  
  1908.             if (isOuter)
  1909.             {
  1910.                 oGapThis(x, y);
  1911.             }
  1912.             else if ((splitType == SPLIT_HORIZONTAL) && outerSP.cursorChanged)
  1913.             {
  1914.                 doMoveSplit = true;
  1915.                 moveFromX = x;
  1916.                 moveFromY = y;
  1917.             }
  1918.             else if ((splitType == SPLIT_VERTICAL) && outerSP.cursorChanged)
  1919.             {
  1920.                 doMoveSplit = true;
  1921.                 moveFromX = x;
  1922.                 moveFromY = y;
  1923.             }
  1924.             else if (outerSP.cursorChanged)
  1925.             {
  1926.                 Point p = location();
  1927.                 SplitterPanel parent = (SplitterPanel)getParent();
  1928.                 if(parent != null)
  1929.                 {
  1930.                     MouseListener parentListener = parent.mouse;//getMouseListener();
  1931.                     if(parentListener != null)
  1932.                         parentListener.mousePressed(new MouseEvent(cursorCh, e.getID(), e.getWhen(), e.getModifiers(), p.x + x, p.y + y, e.getClickCount(), e.isPopupTrigger()));
  1933.                 }
  1934.             }
  1935.         }
  1936.  
  1937.         /**
  1938.          * Handles Mouse Released events
  1939.          * @param e the MouseEvent
  1940.          */
  1941.         public void mouseReleased(MouseEvent e)
  1942.         {
  1943.             int x = e.getX();
  1944.             int y = e.getY();
  1945.  
  1946.             if (isOuter)
  1947.             {
  1948.                 oGapThis(x, y);
  1949.             }
  1950.             //Important -- Do NOT check that this is the target for mouse up
  1951.             else if (doMoveSplit == true)
  1952.             {
  1953.                 moveSplit(x - moveFromX, y - moveFromY);
  1954.                 doMoveSplit = false;
  1955.             }
  1956.         }
  1957.     }
  1958.  
  1959.     /**
  1960.      * This is the MouseMotion Event handling innerclass.
  1961.      */
  1962.     class MouseMtn implements java.awt.event.MouseMotionListener, java.io.Serializable
  1963.     {
  1964.         /**
  1965.          * Handles Mouse Moved events
  1966.          * @param e the MouseEvent
  1967.          */
  1968.         public void mouseMoved(MouseEvent e)
  1969.         {
  1970.             int x = e.getX();
  1971.             int y = e.getY();
  1972.  
  1973.             if (isOuter)
  1974.             {
  1975.                 oGapThis(x, y);
  1976.             }
  1977.             else if ((splitType == SPLIT_HORIZONTAL) && inGap1(x, y))
  1978.             {
  1979.                 setCursor(moveSplitCursor);
  1980.             }
  1981.             else if ((splitType == SPLIT_VERTICAL) && inGap1(x, y))
  1982.             {
  1983.                 setCursor(moveSplitCursor);
  1984.             }
  1985.             else
  1986.             {
  1987.                 if (!doMoveSplit && !inGap(x, y)) resetCursor();
  1988.             }
  1989.         }
  1990.  
  1991.         /**
  1992.          * Handles Mouse Dragged events
  1993.          * @param e the MouseEvent
  1994.          */
  1995.         public void mouseDragged(MouseEvent e)
  1996.         {
  1997.             int x = e.getX();
  1998.             int y = e.getY();
  1999.  
  2000.             if (isOuter)
  2001.             {
  2002.                 oGapThis(x, y);
  2003.             }
  2004.             else if (doMoveSplit == true)
  2005.             {
  2006.                 setCursor(moveSplitCursor);
  2007.                 if(allowDynamicMoving)
  2008.                 {
  2009.                     moveSplit(x - moveFromX, y - moveFromY);
  2010.                     moveFromX = x;
  2011.                     moveFromY = y;
  2012.                 }
  2013.             }
  2014.         }
  2015.     }
  2016.  
  2017.     /**
  2018.      * This is the PropertyChangeEvent handling inner class for the constrained SplitType property.
  2019.      * Handles vetoing SplitTypes that are not valid.
  2020.      */
  2021.     class STVeto implements java.beans.VetoableChangeListener, java.io.Serializable
  2022.     {
  2023.         /**
  2024.          * This method gets called when an attempt to change the constrained SplitType property is made.
  2025.          * Ensures the given SplitType is valid for this component.
  2026.          *
  2027.          * @param     e a <code>PropertyChangeEvent</code> object describing the
  2028.          *             event source and the property that has changed.
  2029.          * @exception PropertyVetoException if the recipient wishes the property
  2030.          *              change to be rolled back.
  2031.          */
  2032.         public void vetoableChange(PropertyChangeEvent e) throws PropertyVetoException
  2033.         {
  2034.             int i = ((Integer)e.getNewValue()).intValue();
  2035.             if (!isValidSplitType(i))
  2036.             {
  2037.                 throw new PropertyVetoException(errors.getString("InvalidSplitType") + i, e);
  2038.             }
  2039.         }
  2040.     }
  2041.  
  2042.     /**
  2043.      * Returns the mouse event handling object.
  2044.      */
  2045.     protected MouseListener getMouseListener()
  2046.     {
  2047.         return mouse;
  2048.     }
  2049.  
  2050.     /**
  2051.      * Utility method to calculate the optimum width or height of a sub-panel.
  2052.      */
  2053.     protected int optSize(int total, int _gap, int _min1, int _min2, int _pref1, int _pref2)
  2054.     {
  2055.         int diff;
  2056.         float scale;
  2057.         int gap;
  2058.         int min1;
  2059.         int min2;
  2060.         int pref1;
  2061.         int pref2;
  2062.  
  2063.         gap  = Math.max(_gap, 0);
  2064.         min1 = Math.max(_min1,  1);
  2065.         min2 = Math.max(_min2,  1);
  2066.         pref1 = Math.max(_pref1,  min1);
  2067.         pref2 = Math.max(_pref2,  min2);
  2068.  
  2069.         diff = total - (pref1 + pref2 + gap);
  2070.  
  2071.         if (diff >= 0)
  2072.         {
  2073.             scale = (float)pref1/(float)(pref1 + pref2);
  2074.             return pref1 + (int)(diff*scale);
  2075.         }
  2076.  
  2077.         diff = total - (min1 + min2 + gap);
  2078.         if (diff >= 0)
  2079.         {
  2080.             scale = (float)pref1/(float)(pref1 + pref2);
  2081.             return min1 + (int)(diff*scale);
  2082.         }
  2083.  
  2084.         if (total > gap)
  2085.         {
  2086.             scale = (float)min1/(float)(min1 + min2);
  2087.             return min1 + (int)(diff*scale);
  2088.         }
  2089.  
  2090.         return total;
  2091.     }
  2092.  
  2093.     /**
  2094.      * Utility method to lay out this component.
  2095.      */
  2096.     protected void placeComponents()
  2097.     {
  2098.         Dimension prefDim1;
  2099.         Dimension prefDim2;
  2100.         Dimension minDim1;
  2101.         Dimension minDim2;
  2102.  
  2103.         int sub1X;
  2104.         int sub1Y;
  2105.         int sub2X;
  2106.         int sub2Y;
  2107.         int sub1Width;
  2108.         int sub1Height;
  2109.         int sub2Width;
  2110.         int sub2Height;
  2111.  
  2112.         Rectangle rect = new Rectangle(curLoc.x, curLoc.y, curDim.width, curDim.height);
  2113.  
  2114.         if (isOuter)
  2115.         {
  2116.             sub1X = oGapWidth  + oBdrSize;
  2117.             sub1Y = oGapHeight + oBdrSize;
  2118.             sub1Width  = rect.width  - ((2 * oGapWidth  + oBdrSize +1 ) );
  2119.             sub1Height = rect.height - ((2 * oGapHeight + oBdrSize + 1) );
  2120.             innerSP.reshape(sub1X, sub1Y, sub1Width, sub1Height);
  2121.         }
  2122.         else
  2123.         {
  2124.             if (sub1 == null)
  2125.             {
  2126.                 minDim1  = new Dimension(1, 1);
  2127.                 prefDim1 = new Dimension(1, 1);
  2128.             }
  2129.             else
  2130.             {
  2131.                 minDim1  = sub1.minimumSize();
  2132.                 prefDim1 = sub1.preferredSize();
  2133.             }
  2134.  
  2135.             if (sub2 == null)
  2136.             {
  2137.                 minDim2  = new Dimension(1, 1);
  2138.                 prefDim2 = new Dimension(1, 1);
  2139.             }
  2140.             else
  2141.             {
  2142.                 minDim2  = sub2.minimumSize();
  2143.                 prefDim2 = sub2.preferredSize();
  2144.             }
  2145.  
  2146.             switch (splitType)
  2147.             {
  2148.                 case SPLIT_NONE:
  2149.                 {
  2150.                     if (spComponent != null)
  2151.                     {
  2152.                         sub1X = iBdrSize;
  2153.                         sub1Y = iBdrSize;
  2154.                         sub1Width  = rect.width  - (2 * iBdrSize);
  2155.                         sub1Height = rect.height - (2 * iBdrSize);
  2156.                         if (sub1Width < 0)
  2157.                             sub1Width = 0;
  2158.                         if (sub1Height < 0)
  2159.                             sub1Height = 0;
  2160.                         if (propResize) spComponent.reshape(sub1X, sub1Y, sub1Width, sub1Height);
  2161.                         else spComponent.move(sub1X, sub1Y);
  2162.                         spComponent.layout();
  2163.                         spComponent.invalidate();
  2164.                         spComponent.validate();
  2165.                         try {
  2166.                             spComponent.repaint();
  2167.                         }
  2168.                         catch(Exception e) {
  2169.                              repaint();
  2170.                         }
  2171.                     }
  2172.  
  2173.                     return;
  2174.                 }
  2175.                 case SPLIT_VER:
  2176.                 {
  2177.                     sub1X = 0;
  2178.                     sub1Y = 0;
  2179.                     sub1Width = optSize(rect.width, iGapWidth, minDim1.width, minDim2.width, prefDim1.width, prefDim2.width);
  2180.                     sub1Height = rect.height;
  2181.  
  2182.                     sub2X = sub1Width + iGapWidth;
  2183.                     sub2Y = 0;
  2184.                     sub2Width = rect.width - sub2X;
  2185.                     sub2Height = rect.height;
  2186.  
  2187.                     break;
  2188.                 }
  2189.                 case SPLIT_HOR:
  2190.                 {
  2191.                     sub1X = 0;
  2192.                     sub1Y = 0;
  2193.                     sub1Width = rect.width;
  2194.                     sub1Height = optSize(rect.height, iGapHeight, minDim1.height, minDim2.height, prefDim1.height, prefDim2.height);
  2195.  
  2196.                     sub2X = 0;
  2197.                     sub2Y = sub1Height + iGapHeight;
  2198.                     sub2Width = rect.width;
  2199.                     sub2Height = rect.height - sub2Y;
  2200.  
  2201.                     break;
  2202.                 }
  2203.                 default:
  2204.                     return;
  2205.  
  2206.             }
  2207.  
  2208.             if (heightOnly)
  2209.             {
  2210.                 heightOnly = false;
  2211.                 sub1.reshapeHeight(sub1Y, sub1Height);
  2212.                 sub2.reshapeHeight(sub2Y, sub2Height);
  2213.             }
  2214.             else if (widthOnly)
  2215.             {
  2216.                 widthOnly = false;
  2217.                 sub1.reshapeWidth(sub1X, sub1Width);
  2218.                 sub2.reshapeWidth(sub2X, sub2Width);
  2219.             }
  2220.             else
  2221.             {
  2222.                 sub1.reshape(sub1X, sub1Y, sub1Width, sub1Height);
  2223.                 sub2.reshape(sub2X, sub2Y, sub2Width, sub2Height);
  2224.             }
  2225.  
  2226.             sub1.invalidate();
  2227.             sub1.validate();
  2228.             sub1.repaint();
  2229.  
  2230.             sub2.invalidate();
  2231.             sub2.validate();
  2232.             sub2.repaint();
  2233.         }
  2234.     }
  2235.  
  2236.     /**
  2237.      * Utility method to draw the border.
  2238.      */
  2239.     protected void draw3DBdr(Graphics g, int x, int y, int width, int height, int bdrSize, Color c, boolean raised)
  2240.     {
  2241.         int i;
  2242.  
  2243.         if (bdrSize < 0)
  2244.             return;
  2245.  
  2246.         g.setColor(use3dBdr ? c : c.darker());
  2247.  
  2248.         for (i = 0; i < bdrSize; i++)
  2249.         {
  2250.             if (use3dBdr) g.draw3DRect(x + i, y + i, width - 2*i, height - 2*i, raised);
  2251.             else g.drawRect(x + i, y + i, width - 2*i, height - 2*i);
  2252.         }
  2253.     }
  2254.  
  2255.     /**
  2256.      * Utility method to update the gap/border/etc properties in sub-panels.
  2257.      */
  2258.     protected void propagateChanges()
  2259.     {
  2260.         if (innerSP != null)
  2261.         {
  2262.             propagateChangesSP(innerSP);
  2263.             innerSP.propagateChanges();
  2264.         }
  2265.  
  2266.         if (sub1 != null)
  2267.         {
  2268.             propagateChangesSP(sub1);
  2269.             sub1.propagateChanges();
  2270.         }
  2271.  
  2272.         if (sub2 != null)
  2273.         {
  2274.             propagateChangesSP(sub2);
  2275.             sub2.propagateChanges();
  2276.         }
  2277.     }
  2278.  
  2279.     /**
  2280.      * Utility method to update the gap/border/etc properties in another panel.
  2281.      * The current property values of this object are copied into the
  2282.      * target object's properties.
  2283.      * @param spTarget the panel to update the properties of
  2284.      */
  2285.     protected void propagateChangesSP(SplitterPanel spTarget)
  2286.     {
  2287.         spTarget.gapColor   = this.gapColor;
  2288.         spTarget.enforceMinDim   = this.enforceMinDim;
  2289.         spTarget.moveSplitCursor = this.moveSplitCursor;
  2290.         spTarget.propResize = this.propResize;
  2291.  
  2292.         if ((spTarget.oGapWidth                != this.oGapWidth)    ||
  2293.             (spTarget.iGapWidth                != this.iGapWidth)    ||
  2294.             (spTarget.oGapHeight            != this.oGapHeight)    ||
  2295.             (spTarget.iGapHeight            != this.iGapHeight)    ||
  2296.             (spTarget.iBdrSize                != this.iBdrSize)    ||
  2297.             (spTarget.oBdrSize                != this.oBdrSize)    ||
  2298.             (spTarget.use3dBdr                != this.use3dBdr)    ||
  2299.             (spTarget.allowDynamicMoving    != this.allowDynamicMoving))
  2300.         {
  2301.             spTarget.oGapWidth            = this.oGapWidth;
  2302.             spTarget.iGapWidth            = this.iGapWidth;
  2303.             spTarget.oGapHeight            = this.oGapHeight;
  2304.             spTarget.iGapHeight            = this.iGapHeight;
  2305.             spTarget.iBdrSize            = this.iBdrSize;
  2306.             spTarget.oBdrSize            = this.oBdrSize;
  2307.             spTarget.use3dBdr            = this.use3dBdr;
  2308.             spTarget.allowDynamicMoving    = this.allowDynamicMoving;
  2309.             layout();
  2310.             spTarget.layout();
  2311.         }
  2312.     }
  2313.  
  2314.     /**
  2315.      * Utility method to create a new Dimension that encompasses the
  2316.      * two input Dimensions.
  2317.      * @param dim1 a dimension
  2318.      * @param dim2 another dimension
  2319.      * @return a Dimension that has the larger of each input dimensions axis
  2320.      */
  2321.     protected Dimension maxDimOf(Dimension dim1, Dimension dim2)
  2322.     {
  2323.         return new Dimension(Math.max(dim1.width, dim2.width), Math.max(dim1.height, dim2.height));
  2324.     }
  2325.  
  2326.     /**
  2327.      * Utility method to set the cursor to the default one.
  2328.      */
  2329.     protected void resetCursor()
  2330.     {
  2331.         if (outerSP.cursorChanged == false)
  2332.             return;
  2333.  
  2334.         try
  2335.         {
  2336.             setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
  2337.             outerSP.cursorChanged = false;
  2338.             cursorCh = null;
  2339.         }
  2340.         catch(IllegalArgumentException e)
  2341.         {
  2342.             return;
  2343.         }
  2344.     }
  2345.  
  2346.     /**
  2347.      * Sets the currently used cursor.
  2348.      * @param cursor the new cursor to use
  2349.      */
  2350.     public synchronized void setCursor(Cursor cursor)
  2351.     {
  2352.         if (outerSP.cursorChanged)
  2353.             return;
  2354.  
  2355.         if (isOuter)
  2356.         {
  2357.             try
  2358.             {
  2359.                 super.setCursor(cursor);
  2360.                 cursorChanged = true;
  2361.             }
  2362.             catch(IllegalArgumentException e)
  2363.             {
  2364.             }
  2365.         }
  2366.         else
  2367.         {
  2368.             outerSP.setCursor(cursor);
  2369.         }
  2370.     }
  2371.  
  2372.     /**
  2373.      * Utility method to determine if the given location is within
  2374.      * the given component.
  2375.      * @param comp the component
  2376.      * @param x the horizontal location
  2377.      * @param y the vertical location
  2378.      * @return true if the location is within the component
  2379.      */
  2380.     protected boolean inComponent(Component comp, int x, int y)
  2381.     {
  2382.         //Point compLoc = comp.location();
  2383.         Rectangle r = comp.bounds();
  2384.         r.grow(-iBdrSize-1, -iBdrSize-1);
  2385.         //return comp.inside(x - compLoc.x, y - compLoc.y);
  2386.         return ((x-r.x >= 0) && (x-r.x <= r.width) && (y-r.y >= 0) && (y-r.y <= r.height));
  2387.     }
  2388.  
  2389.     /**
  2390.      * Utility method to determine if the given location is in the gap
  2391.      * between any nested sub-panels.
  2392.      * @param evtX the horizontal location
  2393.      * @param evtY the vertical location
  2394.      * @return true if the location is within the gap
  2395.      */
  2396.     protected boolean inGap(int evtX, int evtY)
  2397.     {
  2398.         if (inGap1(evtX, evtY))
  2399.             return true;
  2400.  
  2401.         if (isOuter)
  2402.         {
  2403.             return innerSP.inGap(evtX - innerSP.curLoc.x, evtY - innerSP.curLoc.y);
  2404.         }
  2405.         else if ((splitType == SPLIT_HOR) || (splitType == SPLIT_VER))
  2406.         {
  2407.             return (sub1.inGap(evtX - sub1.curLoc.x, evtY - sub1.curLoc.y)  ||
  2408.                     sub2.inGap(evtX - sub2.curLoc.x, evtY - sub2.curLoc.y));
  2409.         }
  2410.  
  2411.         return false;
  2412.     }
  2413.  
  2414.     /**
  2415.      * Utility method to determine if the given location is in the gap
  2416.      * between this panel's sub-panels.
  2417.      * @param evtX the horizontal location
  2418.      * @param evtY the vertical location
  2419.      * @return true if the location is within the gap
  2420.      */
  2421.     protected boolean inGap1(int evtX, int evtY)
  2422.     {
  2423.         if (!inside(evtX, evtY))
  2424.             return false;
  2425.  
  2426.         if (isOuter)
  2427.         {
  2428.             return false;
  2429.         }
  2430.  
  2431.         if (inOutBoarder(evtX, evtY)) {
  2432.             return false;
  2433.         }
  2434.         else if ((splitType == SPLIT_HOR) || (splitType == SPLIT_VER))
  2435.         {
  2436.             if (inComponent(sub1, evtX, evtY) || (inComponent(sub2, evtX, evtY)))
  2437.             {
  2438.                 return false;
  2439.             }
  2440.             else
  2441.             {
  2442.                 if (inComponent(this, evtX, evtY)) cursorCh = this;
  2443.                 return true;
  2444.             }
  2445.         }
  2446.         else
  2447.         {
  2448.             return false;
  2449.         }
  2450.  
  2451.     }
  2452.  
  2453.     /**
  2454.      * Utility method to determine if the given location is in the
  2455.      * border around this component.
  2456.      * @param evtX the horizontal location
  2457.      * @param evtY the vertical location
  2458.      * @return true if the location is within the border
  2459.      */
  2460.     protected boolean inOutBoarder(int evtX, int evtY) {
  2461.         Component sp = this;
  2462.         Rectangle r = sp.bounds();
  2463.         int x = r.x;
  2464.         int y = r.y;
  2465.  
  2466.         while(sp != outerSP) {
  2467.             sp = sp.getParent();
  2468.             r = sp.bounds();
  2469.             x += r.x;
  2470.             y += r.y;
  2471.         }
  2472.         r.grow(-(outerSP.iBdrSize + outerSP.oBdrSize + outerSP.oGapWidth/2+4), -(outerSP.iBdrSize + outerSP.oBdrSize + outerSP.oGapHeight/2+4));
  2473.         r.move(r.x + outerSP.oGapWidth/2, r.y + outerSP.oGapHeight/2);
  2474.         return !r.inside(x + evtX, y + evtY);
  2475.     }
  2476.  
  2477.     /**
  2478.      * Utility method to constrain the gap width/height inside the border to
  2479.      * good values.
  2480.      */
  2481.     protected void adjustOGapBdr()
  2482.     {
  2483.         if (this.oGapWidth  < this.oBdrSize)
  2484.             this.oGapWidth  = Math.max(0, this.oBdrSize);
  2485.  
  2486.         if (this.oGapHeight < this.oBdrSize)
  2487.             this.oGapHeight = Math.max(0, this.oBdrSize);
  2488.     }
  2489.  
  2490.     /**
  2491.      * This flag specifies how to draw the border around panels.
  2492.      * If true, the border around the panel is drawn with a three-dimensional effect.
  2493.      */
  2494.     protected  boolean                use3dBdr = true;
  2495.     /**
  2496.      * Determines the cursor to use when dragging the split between panels.
  2497.      * Use Cursor.HAND_CURSOR, etc to choose a cursor.
  2498.      * @see java.awt.Cursor
  2499.      */
  2500.     protected  Cursor                    moveSplitCursor = new Cursor(Cursor.MOVE_CURSOR);
  2501.     /**
  2502.      * Dimension variables.
  2503.      * Note that these should be set explicitly if you wish to override
  2504.      * the built in calculation of these dimensions.  For instance, do
  2505.      * not set (or set to zeros), the value for prefDim if you want the
  2506.      * SplitterPanel to calculate this as the sum of the subcomponents
  2507.      * prefDims.  minDim is used when the user explicitly sets the
  2508.      * minimum size; prefDim is used when the user explicitly sets the
  2509.      * preferred size.
  2510.      * @see #prefDim
  2511.      */
  2512.     protected Dimension                minDim;
  2513.     /**
  2514.      * Dimension variables.
  2515.      * Note that these should be set explicitly if you wish to override
  2516.      * the built in calculation of these dimensions.  For instance, do
  2517.      * not set (or set to zeros), the value for prefDim if you want the
  2518.      * SplitterPanel to calculate this as the sum of the subcomponents
  2519.      * prefDims.  minDim is used when the user explicitly sets the
  2520.      * minimum size; prefDim is used when the user explicitly sets the
  2521.      * preferred size.
  2522.      * @see #minDim
  2523.      */
  2524.     protected Dimension                prefDim;
  2525.     /**
  2526.      * Current component dimensions.
  2527.      */
  2528.     protected Dimension                curDim;
  2529.     /**
  2530.      * The split width between panels, in pixels.
  2531.      */
  2532.     protected int                        iGapWidth;
  2533.     /**
  2534.      * The split height between panels, in pixels.
  2535.      */
  2536.     protected int                        iGapHeight;
  2537.     /**
  2538.      * The gap width inside the border, in pixels.
  2539.      */
  2540.     protected int                        oGapWidth;
  2541.     /**
  2542.      * The gap height inside the border, in pixels.
  2543.      */
  2544.     protected int                        oGapHeight;
  2545.     /**
  2546.      * The size of the border drawn between panels, in pixels.
  2547.      */
  2548.     protected int                        iBdrSize;
  2549.     /**
  2550.      * The size of the border drawn around the outside of the SplitterPanel,
  2551.      * in pixels.
  2552.      */
  2553.     protected int                        oBdrSize;
  2554.     /**
  2555.      * The type of split for this SplitterPanel.
  2556.      * Value is one of: SPLIT_VERTICAL or SPLIT_HORIZONTAL.
  2557.      * @see #SPLIT_VERTICAL
  2558.      * @see #SPLIT_HORIZONTAL
  2559.      * @see #SPLIT_NONE
  2560.      */
  2561.     protected int                        splitType;
  2562.     /**
  2563.      * Internal use only.
  2564.      */
  2565.     protected int                     moveFromX;
  2566.     /**
  2567.      * Internal use only.
  2568.      */
  2569.     protected int                        moveFromY;
  2570.     /**
  2571.      * Panel contains no subpanels, initial state.
  2572.      */
  2573.     protected static final int        SPLIT_NONE = 0;
  2574.     /**
  2575.      * Internal use only.
  2576.      */
  2577.     transient protected boolean            bOsFlag;
  2578.     /**
  2579.      * Enforce minimum dimension mode flag.
  2580.      * This mode prevents the dragging of a split between panels
  2581.      * from making a panel smaller than the minimum size of its component.
  2582.      * If true, enforces minimum panel dimensions.
  2583.      * @see #isEnforceMinDim
  2584.      * @see #setEnforceMinDim
  2585.      */
  2586.     protected boolean                    enforceMinDim = false;
  2587.     /**
  2588.      * The "resize propagation" mode flag.
  2589.      * If this is false, resizing of SplitterPanel
  2590.      * panels does not automatically call
  2591.      * the contained component's resize() method.
  2592.      * The default behavior propagates the resizing effect of dragging the
  2593.      * split between panes by calling move and resize for the panels that have
  2594.      * been added to those panes.  Clearing this introduces a clipping effect,
  2595.      * rather than a scaling effect.
  2596.      * @see #isPropResize
  2597.      * @see #setPropResize
  2598.      */
  2599.     protected boolean                    propResize = true;
  2600.     /**
  2601.      * Internal use only.
  2602.      */
  2603.     protected boolean                    isOuter;
  2604.     /**
  2605.      * Internal flag indicating a reshape in height only.
  2606.      */
  2607.     protected boolean                    heightOnly;
  2608.     /**
  2609.      * Internal flag indicating a reshape in width only.
  2610.      */
  2611.     protected boolean                    widthOnly;
  2612.     /**
  2613.      * Internal flag indicating split being moved.
  2614.      */
  2615.     transient protected boolean            doMoveSplit = false;
  2616.     /**
  2617.      * Internal use only.
  2618.      */
  2619.     transient protected boolean            cursorChanged = false;
  2620.     /**
  2621.      * This flag specifies if moving of a split in a splitter panel will be real time,
  2622.      * or delayed until mouse released.
  2623.      * @see #isAllowDynamicMoving
  2624.      * @see #setAllowDynamicMoving
  2625.      */
  2626.     protected boolean                    allowDynamicMoving;
  2627.     /**
  2628.      * Sub-panel 1 of 2.
  2629.      */
  2630.     protected SplitterPanel            sub1;
  2631.     /**
  2632.      * Sub-panel 2 of 2.
  2633.      */
  2634.     protected SplitterPanel            sub2;
  2635.     /**
  2636.      * Internal use only.
  2637.      */
  2638.     protected SplitterPanel            innerSP;
  2639.     /**
  2640.      * Internal use only.
  2641.      */
  2642.     protected SplitterPanel            outerSP;
  2643.     /**
  2644.      * Internal use only.
  2645.      */
  2646.     protected static SplitterPanel    cursorCh = null;
  2647.     /**
  2648.      * The current location of this component.
  2649.      */
  2650.     protected Point                    curLoc;
  2651.     /**
  2652.      * The component contained within this panel.
  2653.      */
  2654.     protected Component                spComponent;
  2655.     /**
  2656.      * The color of the gap between panels and around the outside
  2657.      * border.
  2658.      * @see #getGapColor
  2659.      * @see #setGapColor
  2660.      */
  2661.     protected Color                    gapColor;
  2662.  
  2663.     /**
  2664.      * Error strings.
  2665.      */
  2666.     transient protected ResourceBundle errors;
  2667.  
  2668.     private Mouse            mouse        = null;
  2669.     private MouseMtn        mouseMotion    = null;
  2670.     private STVeto            stVeto        = null;
  2671.     private symantec.itools.beans.VetoableChangeSupport vetos = new symantec.itools.beans.VetoableChangeSupport(this);
  2672.     private symantec.itools.beans.PropertyChangeSupport changes = new symantec.itools.beans.PropertyChangeSupport(this);
  2673. }
  2674.